﻿﻿<script setup>

import {ICONS} from "@/const";

import {shallowRef} from "vue";

import {myInsert, myUpdate} from "@/util";



/**

 * type: 表单类型，支持 insert 和 update 两种

 * data: 表单数据

 * rules: 表单规则

 * api: 表单提交的API函数

 * fn: 表单提交后的回调函数

 * width: 表单整体宽度（需要带单位）

 * items:

 *   通用:

 *     label: 文案，默认表单项属性名

 *     prop: 属性名

 *     required: 是否必填，默认 false

 *     disabled: 是否禁用，默认 false

 *     readonly: 是否只读，默认 false

 *     placeholder: 背景字，默认 "type + 表单属性名"

 *   number:

 *     min: 最小值，默认 0

 *     max: 最大值

 *     precision: 精度，默认 0

 *   textarea:

 *     rows: 行数，默认 8

 *     cols: 列数

 *   select:

 *     optionItems:

 *       label: 选项文案

 *       value: 值

 *   icon:

 *     iconSize: 按钮大小，默认 14

 *   date:

 *   其他:

 */

let parent = defineProps({

  'type': {type: String, required: false, default: 'insert'},

  'items': {type: Array, required: true},

  'data': {type: Array, required: true},

  'rules': {type: Object, required: true},

  'api': {type: Function, required: true},

  'fn': {type: Function, required: false},

  'width': {type: String, required: false, default: '100%'},

});



// 表单对象

let form = shallowRef();



// 添加数据: 发送请求 + 重置表单

async function insert() {

  await myInsert({

        'form': form,

        'api': parent['api'],

        'params': parent['data'],

        'fn': parent['fn']

      }

  );

  form.value.resetFields;

}



// 修改数据: 发送请求 + 重置表单

async function update() {

  await myUpdate({

    'form': form,

    'api': parent['api'],

    'params': parent['data'],

    'fn': parent['fn']

  });

  form.value.resetFields;

}

</script>



<template>

  <el-form class="my-form" ref="form" status-icon

           :model="data"

           :rules="rules"

           :style="{'width': width}"

           label-width="auto">



    <el-row :gutter="20">

      <el-col v-for="item in items" :key="item" :span="item['span'] || 24">

        <!--表单内容项-->

        <el-form-item :label="item['label'] || item['prop']"

                      :prop="item['prop']"

                      :required="item['required']" :style="{visibility: item['visibility']}">



          <!--数字框-->

          <el-input-number v-if="item['type'] === 'number'" clearable

                           v-model="data[item['prop']]"

                           :min="item['min'] || 0"

                           :max="item['max']"

                           :precision="item['precision'] || 0"

                           :placeholder="item['placeholder'] || ('type ' + item['prop'])"

                           :disabled="item['disabled']"

                           :readonly="item['readonly']"/>



          <!--文本域-->

          <el-input v-else-if="item['type'] === 'textarea'" type="textarea" resize="none" clearable

                    v-model="data[item['prop']]"

                    :rows="item['rows'] || 8"

                    :cols="item['cols']"

                    :placeholder= "item['placeholder'] || 'type ' + item['prop']"

                    :disabled="item['disabled']"

                    :readonly="item['readonly']"/>



          <!--下拉框-->

          <el-select v-else-if="item['type'] === 'select'" clearable filterable

                     v-model="data[item['prop']]"

                     :disabled="item['disabled']"

                     :readonly="item['readonly']"

                     :placeholder="item['placeholder'] || 'type ' + item['prop']">

            <el-option v-for="optionItem in item['optionItems']" :key="optionItem"

                       :label="optionItem['label']"

                       :value="optionItem['value']"/>

          </el-select>



          <!--时间框-->

          <el-date-picker v-else-if="item['type'] === 'date'" type="datetime" clearable

                          v-model="data[item['prop']]"

                          :placeholder="item['placeholder'] || 'type ' + item['prop']"

                          :disabled="item['disabled']"

                          :readonly="item['readonly']"/>



          <!--ICON单选框-->

          <el-radio-group v-else-if="item['type'] === 'icon'" class="icon-list"

                          v-model="data[item['prop']]" size="small">

            <el-radio-button v-for="icon in ICONS" :key="icon" :label="icon">

              <template #default>

                <el-icon :size="item['iconSize'] || 14">

                  <component :is="icon"/>

                </el-icon>

              </template>

            </el-radio-button>

          </el-radio-group>


          <!--密码框-->
          <el-input v-else-if="item['type'] === 'password'" clearable show-password
                    v-model="data[item['prop']]"
                    :placeholder="item['placeholder'] || ('type ' + item['prop'])"
                    :disabled="item['disabled']" :readonly="item['readonly']"/>
          <!--文本框-->

          <el-input v-else clearable

                    v-model="data[item['prop']]"

                    :placeholder="item['placeholder'] || 'type ' + item['prop']"

                    :disabled="item['disabled']"

                    :readonly="item['readonly']"/>



        </el-form-item>

      </el-col>

    </el-row>



    <!--表单按钮项-->

    <el-form-item class="btn-item">

      <el-button v-if="type === 'insert'" type="primary" @click="insert">确认添加</el-button>

      <el-button v-else-if="type === 'update'" type="primary" @click="update">确认修改</el-button>

    </el-form-item>



  </el-form>

</template>



<style scoped lang="scss">

.my-form {

  .el-input-number, .el-button {

    width: 100%; // 宽度

  }

}



:deep(.el-date-editor) {

  --el-date-editor-width: 100%; // 宽度

}



.icon-list {



  max-height: 180px; // 最大高度

  overflow-y: scroll; // Y滚动



  .el-radio {

    margin-bottom: 3px; // 下外边距

    margin-right: 3px; // 右外边距

  }



}



/*取消首尾按钮的圆角*/

:deep(.el-radio-button:first-child .el-radio-button__inner),

:deep(.el-radio-button:last-child .el-radio-button__inner) {

  border-radius: 0; // 圆角

}



/*修改单选按钮样式*/

:deep(.el-radio-button--small .el-radio-button__inner) {

  border-left: 1px solid #7e7e7e; // 左边框

  margin: 0 2px; // 左右外边距

}

</style>